package com.jxtc.enterprise.tenant.controller;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jxtc.enterprise.common.aspectj.TokenRequired;
import com.jxtc.enterprise.common.dto.DailyOrderCountAndAmountDTO;
import com.jxtc.enterprise.common.entity.DeliveryTask;
import com.jxtc.enterprise.common.mapper.DeliveryTaskMapper;
import com.jxtc.enterprise.common.service.impl.DeliveryCommissionManageServiceImpl;
import com.jxtc.enterprise.common.utils.Result;
import com.jxtc.enterprise.common.utils.ResultGenerator;
import com.jxtc.enterprise.common.vo.PaginationResponseVO;
import com.jxtc.enterprise.tenant.dto.deliveryCommission.DeliveryOrderCalculateDTO;
import com.jxtc.enterprise.tenant.service.TenantDeliveryCommissionManageService;
import com.jxtc.enterprise.tenant.vo.delliveryCommissionManage.DeliveryCommissionVO;
import com.jxtc.enterprise.tenant.vo.delliveryCommissionManage.DeliveryMiscellaneousFeeVO;
import com.jxtc.enterprise.tenant.vo.delliveryCommissionManage.DeliveryTaskBriefInfoVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/jxtc/enterprise/tenant/deliveryCommissionManage")
@RequiredArgsConstructor
@Slf4j
@TokenRequired(role = TokenRequired.ROLE_TENANT)
public class TenantDeliveryCommissionManageController {

    @Autowired
    private DeliveryTaskMapper deliveryTaskMapper;

    @Autowired
    private TenantDeliveryCommissionManageService tenantDeliveryCommissionManageService;

    @Autowired
    private DeliveryCommissionManageServiceImpl deliveryCommissionManageServiceImpl;

    /**
     * 接口 2.9.1 查询配送任务详情列表，配送费用管理页面表格中的数据通过此接口获取
     * 请求参数没有什么特殊的字段，定义VO 比较麻烦，直接使用JSONObject类型，如果其他接口中某些入参需要特殊校验或者特殊的字段，还是建议定义对应的VO类
     * keyword: 骑手姓名或手机号; 公司名称
     *
     * @param requestBody
     */
    @PostMapping("/queryDeliveryCommission")
    public Result<PaginationResponseVO<JSONObject>> queryDeliveryCommission(HttpServletRequest request, @RequestBody JSONObject requestBody) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /queryDeliveryCommission, request body: {}", requestId, requestBody);

        String tenantId = (String) request.getAttribute("userId");
        String keyword = requestBody.getString("keyword");
        String startDateTime = requestBody.getString("startTime");
        String endDateTime = requestBody.getString("endTime");
        int taskStatus = requestBody.getIntValue("taskStatus");
        JSONObject parsedDeliveryAndSettlementStatusObj = tenantDeliveryCommissionManageService.parseDeliveryAndSettlementStatusFromTaskStatus(taskStatus);
        int deliveryStatus = parsedDeliveryAndSettlementStatusObj.getIntValue("deliveryStatus");
        int settlementStatus = parsedDeliveryAndSettlementStatusObj.getIntValue("settlementStatus");
        int pageNo = requestBody.getIntValue("pageNo");
        int pageSize = requestBody.getIntValue("pageSize");

        JSONObject parsedDateTimeObj = tenantDeliveryCommissionManageService.parseDeliveryDateAndTime(startDateTime, endDateTime);
        String startDate = parsedDateTimeObj.getString("startDate");
        String endDate = parsedDateTimeObj.getString("endDate");
        String startTime = parsedDateTimeObj.getString("startTime");
        String endTime = parsedDateTimeObj.getString("endTime");

        Page<DeliveryCommissionVO> page = new Page<>(pageNo, pageSize);
        Page<DeliveryCommissionVO> deliveryCommissionVOPage =
                deliveryTaskMapper.queryDeliveryTaskByRiderNamePhoneOrCompanyName(page, tenantId, keyword, startDate, endDate, startTime, endTime, deliveryStatus, settlementStatus);
        // TODO: 由于每天凌晨 1 点会通过定时任务计算前一天的配送任务的订单数量和订单金额，并写回到 delivery_task 表中。
        //       因此，如果后续该接口响应较慢时，可以仅查询当天的配送任务的订单数量及订单金额，其它日期的配送任务直接使用数据库中保存的数据即可
        // 根据配送任务 ID 列表实时查询当前的配送任务的订单数量及订单金额
        List<String> taskIdList = deliveryCommissionVOPage.getRecords()
                .stream()
                .map(DeliveryCommissionVO::getTaskId)
                .collect(Collectors.toList());
        // 以配送任务 ID 为 key，订单数量和金额为 value 构建一个 Map
        Map<String, DailyOrderCountAndAmountDTO> taskIdToOrderCountMap;
        if (!taskIdList.isEmpty()) {
            // 通过配送任务 ID 列表查询配送任务所对应的订单详情信息，并根据 companyId, mealType, storeId 和 dateFlag 进行分组
            List<DeliveryOrderCalculateDTO> deliveryOrderCalculateList = deliveryTaskMapper.calculateDeliveryOrderCommissionByTaskIdList(taskIdList);
            Map<String, List<DeliveryOrderCalculateDTO>> groupByTaskIdMap = deliveryOrderCalculateList.stream().collect(Collectors.groupingBy(DeliveryOrderCalculateDTO::getTaskId));
            taskIdToOrderCountMap = new HashMap<>(groupByTaskIdMap.size());
            // 将同一个配送任务的订单数量和金额进行累加
            for (Map.Entry<String, List<DeliveryOrderCalculateDTO>> entry : groupByTaskIdMap.entrySet()) {
                String taskId = entry.getKey();
                int orderCount = 0;
                int orderAmount = 0;
                for (DeliveryOrderCalculateDTO deliveryOrderCalculateDTO : entry.getValue()) {
                    orderCount += deliveryOrderCalculateDTO.getOrderCount();
                    orderAmount += deliveryOrderCalculateDTO.getOrderAmount();
                }
                DailyOrderCountAndAmountDTO countAndAmountDTO = new DailyOrderCountAndAmountDTO();
                countAndAmountDTO.setOrderCount(orderCount);
                countAndAmountDTO.setOrderAmount(orderAmount);
                taskIdToOrderCountMap.put(taskId, countAndAmountDTO);
            }
        } else {
            taskIdToOrderCountMap = Collections.emptyMap();
        }

        List<JSONObject> formattedDeliveryCommissions = tenantDeliveryCommissionManageService.formatAndCalculateDeliveryTaskDetails(deliveryCommissionVOPage.getRecords(), taskIdToOrderCountMap);

        PaginationResponseVO<JSONObject> vo = new PaginationResponseVO<>(deliveryCommissionVOPage.getTotal(), deliveryCommissionVOPage.getCurrent(), formattedDeliveryCommissions);

        log.info("requestId {}, /queryDeliveryCommission, response: {}", requestId, JSONObject.toJSONString(vo));
        return ResultGenerator.genSuccessResult(vo);
    }

    /**
     * 2.9.2 查询某一次配送任务详情(公司&取餐店铺等)
     */
    @GetMapping("/queryTaskDetail")
    public Result<?> queryTaskDetail(@RequestParam("taskId") String taskId) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /queryTaskDetail, taskId: {}", requestId, taskId);

        List<DeliveryTaskBriefInfoVO> deliveryTaskBriefInfoVOS = deliveryTaskMapper.queryDeliveryDetailByTaskId(taskId);
        JSONObject formattedTaskBriefInfo = tenantDeliveryCommissionManageService.formatDeliveryTaskBriefInfo(deliveryTaskBriefInfoVOS);

        log.info("requestId {}, /queryTaskDetail, response: {}", requestId, JSONObject.toJSONString(formattedTaskBriefInfo));
        return ResultGenerator.genSuccessResult(formattedTaskBriefInfo);
    }

    /**
     * 2.9.3 查询某一个配送任务的杂项费用(加项，扣除项，备注)
     */
    @GetMapping("/queryTaskMisCellaneousFee")
    public Result<?> queryTaskMisCellaneousFee(@RequestParam("taskId") String taskId) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /queryTaskMisCellaneousFee, taskId: {}", requestId, taskId);
        DeliveryMiscellaneousFeeVO deliveryTaskMiscellaneousFeeVo = deliveryTaskMapper.queryDeliveryMisscellaneousFee(taskId);

        JSONObject formatedMiscellaneousFee = new JSONObject();
        String yuanOfAdditionalFee = tenantDeliveryCommissionManageService.formatFenToYuan(deliveryTaskMiscellaneousFeeVo.getAdditionalFee());
        formatedMiscellaneousFee.put("additionalFee", yuanOfAdditionalFee);
        String yuanOfDuductFee = tenantDeliveryCommissionManageService.formatFenToYuan(deliveryTaskMiscellaneousFeeVo.getDeductFee());
        formatedMiscellaneousFee.put("deductFee", yuanOfDuductFee);
        formatedMiscellaneousFee.put("note", deliveryTaskMiscellaneousFeeVo.getNote());

        log.info("requestId {}, /queryTaskMisCellaneousFee, before formated: {},  response: {}", requestId,
                JSONObject.toJSONString(deliveryTaskMiscellaneousFeeVo),
                JSONObject.toJSONString(formatedMiscellaneousFee));

        return ResultGenerator.genSuccessResult(formatedMiscellaneousFee);
    }

    /**
     * 2.9.4 编辑某一次配送任务的杂项佣金(加项&扣除项)
     */
    @PostMapping("/editTaskMiscellaneousFee")
    public Result<?> editTaskMiscellaneousFee(@RequestBody JSONObject requestBody) {

        String taskId = requestBody.getString("taskId");
        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /editTaskMiscellaneousFee, taskId: {}", requestId, taskId);
        String additionFee = requestBody.getString("additionFee");
        int additionFeeInt = (int) (Double.parseDouble(additionFee) * 100);
        String deductFee = requestBody.getString("deductFee");
        int deductFeeInt = (int) (Double.parseDouble(deductFee) * 100);
        String note = requestBody.getString("note");

        int updatedCount = deliveryTaskMapper.update(new LambdaUpdateWrapper<DeliveryTask>()
                .set(DeliveryTask::getAdditionalFee, additionFeeInt)
                .set(DeliveryTask::getDeductFee, deductFeeInt)
                .set(DeliveryTask::getNote, note)
                .set(DeliveryTask::getUpdateTime, LocalDateTime.now())
                .eq(DeliveryTask::getId, taskId));

        log.info("requestId {}, /editTaskMiscellaneousFee, update record count: {}", requestId, updatedCount);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 2.9.5 查询结算凭证
     */
    @GetMapping("/querySettlementProofs")
    public Result<?> querySettlementProofs(@RequestParam("taskId") String taskId) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /querySettlementProofs, taskId: {}", requestId, taskId);
        String proofImages = deliveryTaskMapper.queryDeliveryTaskProofImages(taskId);
        log.info("requestId {}, /querySettlementProofs, proof images: {}", requestId, proofImages);
        return ResultGenerator.genSuccessResult(proofImages);
    }

    /**
     * 2.9.6 批量录入结算凭证时，为多个配送任务上传结算凭证图片
     */
    @PostMapping("/batchSaveSettlementProofs")
    public Result<?> batchSaveSettlementProofs(@RequestBody JSONObject requestBody) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /batchSaveSettlementProofs, request body: {}", requestId, JSONObject.toJSONString(requestBody));
        JSONArray taskIds = requestBody.getJSONArray("taskIds");
        List<String> taskIdList = taskIds.toJavaList(String.class);
        JSONArray proofImages = requestBody.getJSONArray("proofImages");
        List<String> proofImageList = proofImages.toJavaList(String.class);
        int updatedCount = deliveryTaskMapper.update(
                new LambdaUpdateWrapper<DeliveryTask>()
                        .set(DeliveryTask::getProofImages, proofImageList)
                        .set(DeliveryTask::getUpdateTime, LocalDateTime.now())
                        .in(DeliveryTask::getId, taskIdList));

        log.info("requestId {}, /batchSaveSettlementProofs, batch import {} settlement proofs", requestId, updatedCount);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 2.9.7 查询结算凭证
     */
    @PostMapping("/confirmSettlement")
    public Result<?> confirmSettlement(@RequestBody JSONArray requestBody) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /confirmSettlement, request body: {}", requestId, JSONObject.toJSONString(requestBody));
        int confirmedTaskCount = deliveryTaskMapper.update(new LambdaUpdateWrapper<DeliveryTask>()
                .set(DeliveryTask::getDeliveryStatus, true)
                .set(DeliveryTask::getUpdateTime, LocalDateTime.now())
                .in(DeliveryTask::getId, requestBody.toJavaList(String.class)));

        log.info("requestId {}, /confirmSettlement, batch confirmed task count: {}", requestId, confirmedTaskCount);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 2.9.8 删除某个配送任务(只能删除状态为 未配送的任务)
     */
    @GetMapping("/deleteUnDeliveriedTask")
    public Result<?> deleteUnDeliveriedTask(@RequestParam("taskId") String taskId) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /deleteUnDeliveriedTask, taskId: {}", requestId, taskId);
        int deletedTaskCount = deliveryTaskMapper.update(new LambdaUpdateWrapper<DeliveryTask>()
                .set(DeliveryTask::getDelFlag, true)
                .set(DeliveryTask::getUpdateTime, LocalDateTime.now())
                .in(DeliveryTask::getId, taskId));

        log.info("requestId {}, /deleteUnDeliveriedTask, delete record count: {}", requestId, deletedTaskCount);
        return ResultGenerator.genSuccessResult();
    }

    /**
     * 2.9.9 导出配送任务到excel文件
     */
    @GetMapping("/exportDeliveryTaskToExcel")
    public Result<?> exportDeliveryTaskToExcel(HttpServletRequest request, HttpServletResponse response, @RequestBody JSONObject requestBody) {

        String requestId = UUID.randomUUID().toString();
        log.info("requestId {}, tenant view, /exportDeliveryTaskToExcel, request body: {}", requestId, requestBody);

        String tenantId = (String) request.getAttribute("userId");
        String keyword = requestBody.getString("keyword");
        String startDateTime = requestBody.getString("startTime");
        String endDateTime = requestBody.getString("endTime");
        int taskStatus = requestBody.getIntValue("taskStatus");
        JSONObject parsedDeliveryAndSettlementStatusObj = tenantDeliveryCommissionManageService.parseDeliveryAndSettlementStatusFromTaskStatus(taskStatus);
        int deliveryStatus = parsedDeliveryAndSettlementStatusObj.getIntValue("deliveryStatus");
        int settlementStatus = parsedDeliveryAndSettlementStatusObj.getIntValue("settlementStatus");
        int pageNo = requestBody.getIntValue("pageNo");
        int pageSize = requestBody.getIntValue("pageSize");

        JSONObject parsedDateTimeObj = tenantDeliveryCommissionManageService.parseDeliveryDateAndTime(startDateTime, endDateTime);
        String startDate = parsedDateTimeObj.getString("startDate");
        String endDate = parsedDateTimeObj.getString("endDate");
        String startTime = parsedDateTimeObj.getString("startTime");
        String endTime = parsedDateTimeObj.getString("endTime");

        Page<DeliveryCommissionVO> page = new Page<>(pageNo, pageSize);
        List<DeliveryCommissionVO> deliveryCommissionVOList =
                deliveryTaskMapper.queryDeliveryTaskByRiderNamePhoneOrCompanyNameForExport(page, tenantId, keyword, startDate, endDate, startTime, endTime,
                        deliveryStatus, settlementStatus);

        List<JSONObject> formattedDeliveryTaskDetails = tenantDeliveryCommissionManageService.formatDeliveryTaskDetails(deliveryCommissionVOList);
        tenantDeliveryCommissionManageService.exportDeliveryTaskDetailToExcel(formattedDeliveryTaskDetails, response);

        log.info("requestId {}, /exportDeliveryTaskToExcel, export to excel successfully", requestId);
        return ResultGenerator.genSuccessResult();
    }

}
